/**
 *
 */
package com.zhisheng.core.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Simple utility class for working with the reflection API and handling
 * reflection exceptions.
 * 
 * 
 * @author Downpour
 * @author Carl
 */
public abstract class ReflectionUtils {
    
    /**
     * Simply create a new instance of a Class, assume that the class has the default constructor
     * 
     * @param clazz
     * @return
     */
    public static Object newInstance(Class<?> clazz) {
        try {
            return clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * Get all the fields of a Class including its super class
     * 
     * @return
     */
    public static List<Field> getAllDeclaredFields(Class<?> clazz) {
    	List<Field> fields = new ArrayList<Field>();
    	
    	while(clazz != null) {
    		
    		for(Field field : clazz.getDeclaredFields()) {
    			fields.add(field);
    		}
    		
    		clazz = clazz.getSuperclass();
    		
    	}
    	
    	return fields;
    }

	/**
	 * Do a wrap for org.springframework.util.ReflectionUtils#makeAccessible(Field) 
	 * 
	 * @param field
	 * @see org.springframework.util.ReflectionUtils#makeAccessible(Field)
	 */
	public static void makeAccessible(Field field) {
		org.springframework.util.ReflectionUtils.makeAccessible(field);
	}

	/**
	 * Set field value and do a wrap for {@link org.springframework.util.ReflectionUtils#setField(Field, Object, Object)} 
	 * 
	 * @param field
	 * @param target
	 * @param value
	 * @see org.springframework.util.ReflectionUtils#setField(Field, Object, Object)
	 */
	public static void setField(Field field, Object target, Object value) {
		ReflectionUtils.makeAccessible(field);
	    org.springframework.util.ReflectionUtils.setField(field, target, value);
	}

	/**
	 * Set the field represented by the supplied field object on the specified
	 * target object to the specified value. Autobox value when the field is
	 * primitive type.
	 * 
	 * @param field
	 * @param target
	 * @param value
	 */
	public static void setField(Field field, Object target, String value) {
	    ReflectionUtils.makeAccessible(field);
	    Class<?> type = field.getType();
		if (String.class.equals(type)) {
			try {
				field.set(target, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		} else {
			Object convertedValue = TypeConverterUtils.parse(value, type);
			org.springframework.util.ReflectionUtils.setField(field, target, convertedValue);
		}
	}

}
